package com.bingo.generate.comm.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.function.Function;
import java.util.stream.Stream;

public class FileUtils {

    //  如果不存在就创建
    public static void safeCreate(Path path){
        if(Files.exists(path)){
            return;
        }
        try {
            Files.createFile(path);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    //  如果存在就删除
    public static void safeDelete(Path path){
        if(!Files.exists(path)){
            return;
        }
        if(Files.isDirectory(path)){
            List<Path> childPaths=getChildPaths(path);
            for (Path childPath : childPaths) {
                safeDelete(childPath);
            }
        }
        try {
            System.out.println("删除文件:"+path);
            Files.delete(path);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    //  如果不存在就创建
    public static void safeCreateDir(Path path){
        if(Files.exists(path)){
            return;
        }
        try {
            Files.createDirectory(path);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    //  保存文件，默认为utf-8模式 如果文件不存在，就创建，如果文件夹不存在，也继续创建
    //  会重写某个文件
    public static void rewrite(Path path,String content){
        safeCreate(path);
        try {
            Files.write(path,content.getBytes(Charset.forName("utf-8")));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public void save(Properties properties){

    }

    public static void copy(Path sourcePath,Path targetPath){
        try {
            Files.copy(sourcePath,targetPath);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static void deepCopy(Path sourcePath,Path targetPath){
        try {
            if(!Files.exists(targetPath)){
                Files.copy(sourcePath,targetPath);
            }
            List<Path> childPaths=getChildPaths(sourcePath);
            for (Path childPath : childPaths) {
                Path childTargetPath=PathUtils.append(targetPath,childPath.getFileName().toString());
                deepCopy(childPath,childTargetPath);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static List<Path> getChildPaths(Path path){
        if(!Files.isDirectory(path)){
            return Collections.EMPTY_LIST;
        }
        List<Path> list=new ArrayList<>();
        try(Stream<Path> stream = Files.list(path)) {
            stream.forEach(item->{
                list.add(item);
            });
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return list;
    }

    public static List<String> readLines(Path path){
        try {
            return Files.readAllLines(path);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static <T> T fnInputStream(Path path, MyFun<InputStream,T> fn){
        if(!Files.exists(path)){
            return null;
        }
        File file=path.toFile();
        /*
        以下的写法会报错:需要将fis定义在局部
        FileInputStream fis=null;
        try(fis = new FileInputStream(file)) {

        } catch (IOException e) {
            e.printStackTrace();
        }*/
        Object res=null;
        try (FileInputStream fis2 = new FileInputStream(file)) {
            res= fn.apply2(fis2);
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
        if(res==null){
            return null;
        }
        return (T) res;
    }

    public static interface MyFun<T,R> extends Function<T,R> {
        default R apply(T t){
            try {
                return apply2(t);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        };

        R apply2(T t) throws IOException;

    }

}
